<template>
  <div class="create-wrapper">
    <div class="tools-header">
      <h2
        class="add-tool"
        style="display: flex; align-items: center; cursor: pointer"
      >
        <el-icon :size="24" style="margin-right: 20px" @click="router.back()"
          ><ArrowLeft
        /></el-icon>
        {{ $route?.params?.id ? '编辑' : '添加' }}会议
      </h2>
    </div>
    <el-card>
      <el-form
        ref="ruleFormRef"
        :model="ruleForm"
        :rules="rules"
        :inline="true"
        class="demo-ruleForm demo-form-inline"
        :size="formSize"
        status-icon
        label-width="auto"
        scroll-to-error
      >
        <el-row justify="center" :gutter="20">
          <el-col :span="12">
            <el-form-item label="会议名称" prop="name">
              <el-input v-model="ruleForm.name" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="会议时间" prop="between">
              <el-date-picker
                class="w-350"
                v-model="ruleForm.between"
                type="datetimerange"
                range-separator="~"
                clearable
                start-placeholder="开始时间"
                end-placeholder="结束时间"
                format="YYYY-MM-DD HH:mm:ss"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="会议地点" prop="location">
              <el-input v-model="ruleForm.location" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row justify="center">
          <el-col :span="24">
            <el-form-item label="会议主题" prop="theme" style="width: 100%">
              <el-input
                v-model="ruleForm.theme"
                type="textarea"
                :autosize="{ minRows: 4, maxRows: 6 }"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row justify="center" :gutter="20">
          <el-col :span="24">
            <el-form-item label="参会人员" style="width: 100%">
              <el-select
                multiple
                filterable
                remote
                v-model="ruleForm.participants"
                reserve-keyword
                placeholder="请搜索选择参会人员"
                remote-show-suffix
                :remote-method="remoteMethod"
                :loading="loading"
                style="width: 100%"
                clearable
              >
                <el-option
                  v-for="item in participantList"
                  :key="item.user_info_id"
                  :label="item.name"
                  :value="item.user_info_id"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row justify="center" :gutter="20">
          <el-col :span="12">
            <el-form-item label="发起人">
              <el-input v-model="ruleForm.promoter" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="记录人" prop="recorder">
              <el-input v-model="ruleForm.recorder" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="主持人" prop="president">
              <el-input v-model="ruleForm.president" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="外部参会人" prop="foreign">
              <el-input v-model="ruleForm.foreign" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item
              label="会议录音"
              prop="material"
              style="align-items: center !important"
            >
              <div class="upload-wrapper">
                <el-upload
                  :show-file-list="false"
                  class="upload-demo"
                  :action="actionURL"
                  multiple
                  name="files"
                  :before-upload="beforeUpload"
                  :on-success="successAction"
                  :on-progress="handleProgress"
                  :on-error="handleError"
                  enctype="multipart/form-data"
                  accept="audio/*,video/*"
                  :disabled="isUpload"
                >
                  <el-button
                    type="primary"
                    :disabled="isUpload"
                    :loading="isUpload"
                    >上传音频</el-button
                  >
                  <template #file="UploadFile">
                    <div class="el-upload__tip">
                      {{ UploadFile }}
                    </div>
                  </template>
                </el-upload>
                <div class="drag-wrapper" v-if="fileList.length">
                  <vue-draggable-next
                    v-model="fileList"
                    :options="{
                      animation: 150,
                      ghostClass: 'sortable-ghost',
                      chosenClass: 'chosenClass',
                      scroll: true,
                      scrollSensitivity: 200,
                    }"
                    class="sortable-wrapper"
                  >
                    <transition-group>
                      <div
                        class="audio-item"
                        v-for="(item, index) in fileList"
                        :key="index"
                      >
                        <el-icon :size="24"><VideoPlay /></el-icon>
                        <span>{{ item.file_name }}</span>
                        <el-icon
                          style="cursor: pointer"
                          class="audio-item__delete"
                          @click="beforeRemove(item)"
                          ><Delete
                        /></el-icon>
                      </div>
                    </transition-group>
                  </vue-draggable-next>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <!-- 上传会议资料 -->
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item
              label="会议资料"
              prop="annex"
              style="align-items: center !important"
            >
              <div class="upload-wrapper">
                <el-upload
                  :show-file-list="true"
                  class="upload-demo"
                  :action="actionFileURL"
                  multiple
                  name="files"
                  :before-upload="beforeUploadFile"
                  :on-success="handleSuccessFile"
                  :on-exceed="handleExceedFile"
                  :on-progress="handleProgressFile"
                  :on-error="handleError"
                  :data="{ file_type: 'meeting' }"
                  enctype="multipart/form-data"
                  accept="
                  .xlsx,.xls,.doc,.docx
                  image/jpeg,image/png,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,
                  text/plain"
                >
                  <el-button
                    type="primary"
                    :disabled="uploadFileLoading"
                    :loading="uploadFileLoading"
                    >上传会议资料</el-button
                  >
                  <template #file="UploadFile">
                    <div class="el-upload__tip">
                      {{ UploadFile }}
                    </div>
                  </template>
                </el-upload>
                <div class="drag-wrapper" v-if="meetingFileList.length">
                  <div class="sortable-wrapper">
                    <div
                      class="audio-item"
                      v-for="(item, index) in meetingFileList"
                      :key="index"
                    >
                      <div
                        style="
                          cursor: pointer;
                          display: flex;
                          align-items: center;
                        "
                        @click="handlePreview(item)"
                      >
                        <el-icon :size="24"><Document /></el-icon>
                        <span>{{ item.file_name }}</span>
                      </div>
                      <el-icon
                        style="cursor: pointer"
                        class="audio-item__delete"
                        @click="beforeRemove(item, 'file')"
                        ><Delete
                      /></el-icon>
                    </div>
                  </div>
                </div>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
        <div
          class="footer"
          style="display: flex; justify-content: center; align-items: center"
        >
          <el-button
            type="primary"
            :loading="submitLoading || isUpload"
            @click="submitForm(ruleFormRef)"
          >
            提交
          </el-button>
          <el-button @click="resetForm(ruleFormRef)">取消</el-button>
        </div>
      </el-form>
    </el-card>
  </div>
  <document-viewer
    :file-name="showFileName"
    :ext="showFileExt"
    v-model:show="showFileEnable"
    :url="showFileUrl"
  />
</template>

<script setup>
import { ref, reactive, watch } from 'vue'
import { VueDraggableNext } from 'vue-draggable-next'
import { useRoute, useRouter } from 'vue-router'
import DocumentViewer from '@/components/document-viewer/index.vue'
import {
  httpCreateMeeting,
  httpUpdateMeeting,
  deleteAudioFile,
  httpSelectMeeting,
  httpGetMeetingPeoples,
} from '@/api/meeting.js'
import { ElMessageBox, ElMessage, ElLoading } from 'element-plus'
import { debounce } from '@/utils/tools.ts'
const actionURL = import.meta.env.VITE_BASE_API + '/audios/upload'
const actionFileURL = import.meta.env.VITE_BASE_API + '/annex/upload'
const route = useRoute()
const ruleFormRef = ref()
const formSize = ref('default')
const router = useRouter()
const isEdit = ref(!!(route.params && route.params.id))
const isUpload = ref(false)
const ruleForm = reactive({
  name: '', // 会议名称
  location: '', // 会议地点
  theme: '', // 会议主题
  participants: undefined, // 参会人员
  promoter: '', // 发起人
  recorder: '', // 记录人
  president: '', // 主持人
  material: [], // 会议音频列表
  meeting_start: '', // 开始时间
  meeting_end: '', // 结束时间
  between: [], // 开始时间 结束时间
  foreign: '', //外部参会人
  annex: [], // 会议资料
})
const participantList = ref([]) // 参会人员
const fileList = ref([]) // 上传的音频
const imageSuffix = import.meta.env.VITE_IMAGE_SUFFIX
const meetingFileList = ref([])
const handleProgress = async () => {
  isUpload.value = true
}
const handleError = () => {
  ElMessage({
    message: '网络不给力，请重新上传',
    type: 'error',
  })
}
const beforeUpload = (file, max_size = 30000) => {
  let type_arr = ['audio', 'video']
  let type = file.type.split('/')[0]
  if (!type_arr.includes(type)) {
    ElMessage.error('音频格式不正确,只支持audio类型')
    return false
  }
  if (file.size > 1024 * 1024 * max_size) {
    ElMessage.error(`音频大小请不要超过${max_size}M`)
    return false
  }
}
const handleUploadRadio = (rule, value, callback) => {
  if (fileList.value.length === 0) {
    callback(new Error('请上传会议材料'))
  } else {
    callback()
  }
}
const rules = reactive({
  name: [{ required: true, message: '请输入会议名称', trigger: 'blur' }],
  material: [
    {
      required: true,
      message: '请上传会议材料',
      trigger: ['blur', 'change'],
      validator: handleUploadRadio,
    },
  ],
  between: [
    {
      required: true,
      message: '请选择时间',
      trigger: ['blur', 'change'],
      validator: (rule, value, callback) => {
        if (!value.length) {
          callback(new Error('请上传会议材料'))
        } else {
          callback()
        }
      },
    },
  ],
})
const loading = ref(false)
const getPeopleList = async (name = '') => {
  loading.value = true
  let list = []
  try {
    const { list } = await httpGetMeetingPeoples({ name_code: name })
    if (!list.length) return
    participantList.value = list.filter((item) => {
      item.name = item.name + item.code
      return name ? item.name.toLowerCase().includes(name.toLowerCase()) : item
    })
  } finally {
    loading.value = false
  }
  return list
}
const remoteMethod = debounce(getPeopleList, 500)

const deleteFiles = (item, file) => {
  if (!file) {
    fileList.value = fileList.value.filter(
      (item1) => item1.file_id != item.file_id,
    )
  } else {
    meetingFileList.value = meetingFileList.value.filter(
      (item1) => item1.file_id != item.file_id,
    )
  }
  ElMessage.success('删除成功')
}
/**
 * 删除上传的文件 音频和附件
 * @param {*} item
 * @param {*} file
 */
const beforeRemove = (item, file) => {
  return ElMessageBox.confirm(`确定删除 ${item.file_name} ?`).then(
    async () => {
      if (!isEdit.value) {
        deleteAudioFile({
          file_id: item.file_id,
        })
          .then((res) => {
            deleteFiles(item, file)
          })
          .catch((err) => {
            ElMessage.error('删除失败')
          })
      } else {
        deleteFiles(item, file)
      }
    },
    () => {},
  )
}
const successAction = (response) => {
  ElLoading.service({ fullscreen: true }).close()
  isUpload.value = false
  if (response.code !== 200) {
    ElMessage.error(response.message)
    return
  }
  const d = response.data.list[0]
  fileList.value.push({
    file_id: d.file_id,
    is_hover: false,
    file_name: d.file_name,
    id: d.id,
    url: imageSuffix + d.file_id,
  })
  ruleFormRef.value.validateField('material')
}
const submitLoading = ref(false)
/**
 * 提交 新增和编辑
 * @param {*} formEl
 */
const submitForm = async (formEl) => {
  if (!formEl) return
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      // @ts-ignore
      let data = {
        ...ruleForm,
        meeting_start: ruleForm.between[0],
        meeting_end: ruleForm.between[1],
      }

      delete data.extra
      delete data.between
      try {
        submitLoading.value = true
        data.material = fileList.value.map((x) => x.id)
        data.annex = meetingFileList.value.map((c) => c.id)
        let res
        if (!isEdit.value) {
          res = await httpCreateMeeting(data)
        } else {
          data.meeting_id = parseInt(route.params.id)
          res = await httpUpdateMeeting(data)
        }
        if (!res) {
          return ElMessage.error(`${isEdit.value ? '更新' : '创建'}` + '失败')
        } else {
          ElMessage.success(`${isEdit.value ? '更新' : '创建'}` + '成功')
          router.push('/meeting/record')
        }
      } catch (err) {
        ElMessage.error('请求失败')
      } finally {
        submitLoading.value = false
      }
    } else {
      console.log('error submit!', fields)
    }
  })
}
/**
 * 取消
 */
const resetForm = (formEl) => {
  router.back()
}
/**
 * 编辑初始化
 */
const initData = async () => {
  if (route.params?.id) {
    const res = await httpSelectMeeting({
      meeting_id: parseInt(route.params?.id),
    })
    if (res.list && res.list.length) {
      let obj = res.list[0]
      if (obj.participants.length) {
        obj.participants.forEach((element) => {
          element.name = element.name + element.code
          participantList.value.push(element)
        })
      }
      ruleForm.name = obj.name
      ruleForm.location = obj.location
      ruleForm.material = obj.material
      ruleForm.between = [
        obj.meeting_start.replace('T', ' '),
        obj.meeting_end.replace('T', ' '),
      ]
      ruleForm.participants =
        obj.participants && obj.participants.map((x) => x.user_info_id)
      ruleForm.promoter = obj.promoter
      ruleForm.recorder = obj.recorder
      ruleForm.president = obj.president
      ruleForm.theme = obj.theme
      ruleForm.annex = obj.annex
      ruleForm.foreign = obj.foreign
      fileList.value = obj.material
      meetingFileList.value = obj.annex
    }
  }
}

watch(
  () => route.params?.id,
  () => {
    initData()
  },
  {
    immediate: true,
  },
)
const getFileExt = (filename) => {
  const name_arr = filename.split('.')
  if (name_arr.length <= 1) {
    return '._'
  } else {
    return '.' + name_arr[name_arr.length - 1]
  }
}
// 上传会议附件
const beforeUploadFile = (file) => {
  const allowedTypes = [
    'doc',
    'docx',
    'xls',
    'xlsx',
    'ppt',
    'pptx',
    'pdf',
    'txt',
    'jpg',
    'jpeg',
    'png',
  ]
  const extension = file.name.split('.').pop() // 获取文件扩展名
  const isAllowed = allowedTypes.includes(extension)
  if (!isAllowed) {
    this.$message.error('只支持 doc, excel, ppt, pdf, txt 文件类型')
    return false // 不允许上传
  }
  return true // 允许上传
}
const uploadFileLoading = ref(false)

const handleSuccessFile = (response) => {
  ElLoading.service({ fullscreen: true }).close()
  uploadFileLoading.value = false
  if (response.code !== 200) {
    ElMessage.error(response.message)
    return
  }
  const d = response.data.list[0]
  meetingFileList.value.push({
    file_id: d.file_id,
    is_hover: false,
    file_name: d.file_name,
    id: d.id,
    url: imageSuffix + 'meeting/' + d.file_id,
  })
}
const handleExceedFile = (item) => {}
const handleProgressFile = () => {
  uploadFileLoading.value = true
}
const showFileEnable = ref(false)
const showFileUrl = ref('')
const showFileName = ref('')
const showFileExt = ref('')
const host = import.meta.env.VITE_BASE_API
const handlePreview = (item) => {
  showFileExt.value = getFileExt(item.file_name)
  showFileName.value = item.file_name
  showFileUrl.value = host + `/file/download?file_id=${item.file_id}&preview=1`
  showFileEnable.value = true
}
</script>

<style scoped lang="scss">
:deep(.el-upload-list) {
  display: none !important;
}
.upload-wrapper {
  display: flex;
  align-items: center;
  width: 100% !important;
}
.drag-wrapper {
  width: 100%;
  border-radius: 4px;
  margin-left: 10px;
  .sortable-wrapper {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    align-items: center;
    border: 1px solid #ccc;
    border-radius: 1px;
    padding: 10px;
  }
  .audio-item {
    display: flex;
    gap: 4px;
    padding: 2px 10px;
    width: fit-content;
    height: 40px;
    align-items: center;
    box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
  }
}
</style>
